import { EventMgr } from "../event/EventMgr";
import { Bits } from "../util/Bits";
import { Cls } from "../util/Defined";
import { ECSCmp } from "./ECSCmp";
import { ECSEntity } from "./ECSEntity";

/** [ECS]过滤器参数 */
export interface IECSFilter {
	[key: string]: Cls<ECSCmp>[];
	/** 包含组件(有其一则匹配) */
	includeOne?: Cls<ECSCmp>[];
	/** 包含组件(都有才匹配) */
	includeAll?: Cls<ECSCmp>[];
	/** 排除组件(有其一则排除) */
	excludeOne?: Cls<ECSCmp>[];
	/** 排除组件(都有才排除) */
	excludeAll?: Cls<ECSCmp>[];
}

/** [ECS]过滤器bits参数 */
export type IECSFilterBits = {
	[key in keyof IECSFilter]: Bits;
};

/** [ECS]过滤器事件 */
export const enum ECSFilterEvent {
	entityAdd = "entityAdd",
	entityRemove = "entityRemove",
}

/** [ECS]过滤器事件携带参数 */
export interface ECSFilterEventData {
	[ECSFilterEvent.entityAdd]: ECSEntity;
	[ECSFilterEvent.entityRemove]: ECSEntity;
}
/**
 * [ECS]过滤器
 */
export class ECSFilter extends EventMgr<ECSFilterEventData> {
	/** 匹配到的所有实体 */
	readonly entitySet = new Set<ECSEntity>();
	/** 发生变化的实体 */
	protected readonly _dirtyEntitySet = new Set<ECSEntity>();

	constructor(protected _filter: IECSFilterBits) {
		super();
	}

	/**
	 * 实体发生变化
	 * @param entity 实体
	 */
	onEntityUpdate(entity: ECSEntity) {
		this._dirtyEntitySet.add(entity);
	}

	protected addEntity(entity: ECSEntity) {
		this.entitySet.add(entity);
		this.send(ECSFilterEvent.entityAdd, entity);
	}

	protected removeEntity(entity: ECSEntity) {
		this.entitySet.delete(entity);
		this.send(ECSFilterEvent.entityRemove, entity);
	}

	/**
	 * 更新有组件变化的实体
	 * 检查实体当前的组件是否与筛选条件匹配
	 */
	update() {
		if (this._dirtyEntitySet.size > 0) {
			this._dirtyEntitySet.forEach(this.updateEntity, this);
			this._dirtyEntitySet.clear();
		}
	}

	private updateEntity(entity: ECSEntity) {
		if (entity.removed) {
			if (this.entitySet.has(entity)) {
				this.removeEntity(entity);
			}
		} else {
			if (this.checkMatch(entity.cmpBits)) {
				if (!this.entitySet.has(entity)) {
					this.addEntity(entity);
				}
			} else {
				if (this.entitySet.has(entity)) {
					this.removeEntity(entity);
				}
			}
		}
	}

	/**
	 * 检查组件bits是否与当前筛选条件匹配
	 * @param cmpBits 实体组件bits
	 */
	checkMatch(cmpBits: Bits) {
		if (this._filter.includeOne && !cmpBits.includeOne(this._filter.includeOne)) {
			return false;
		}
		if (this._filter.includeAll && !cmpBits.include(this._filter.includeAll)) {
			return false;
		}
		if (this._filter.excludeOne && cmpBits.includeOne(this._filter.excludeOne)) {
			return false;
		}
		if (this._filter.excludeAll && cmpBits.include(this._filter.excludeAll)) {
			return false;
		}
		return true;
	}

	/**
	 * 销毁过滤器
	 */
	destroy() {
		this.offAll();
		this.entitySet.clear();
		this._dirtyEntitySet.clear();
		this._filter = null;
	}
}
